package com.iob.coin.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.iob.coin.covid19kg.dataset.DefaultURI;
import org.apache.jena.vocabulary.RDF;
import org.apache.jena.vocabulary.RDFS;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author: GuoXinyuan
 * @Date: 2021/6/6
 */

public class KG {

    private final AtomicInteger typeId = new AtomicInteger(1);
    private final AtomicInteger nodeId = new AtomicInteger(1);
    private final AtomicInteger propertyId = new AtomicInteger(1);

    public KG(){
        typesMap = new HashMap<>();
        nodesMap = new HashMap<>();
        properties = new HashSet<>();
        buildBaseType();
    }

    @JsonIgnore
    private final HashMap<String,Node> typesMap; //<uri,node> 图谱内部结构，不对外暴露

    @JsonIgnore
    private final HashMap<String,Node> nodesMap; //<uri,node> 图谱内部结构，不对外暴露

    private final Set<Node> types = null; //代表当前图谱的类型集合 对外暴露 但本身不存储任何信息

    private final Set<Node> nodes = null; //代表当前图谱的节点集合 对外暴露 但本身不存储任何信息

    private final Set<Triple> properties;

    public Set<Node> getTypes() {
        Set<Node> result = new HashSet<>();
        typesMap.keySet().forEach((key)-> result.add(typesMap.get(key)));
        return result;
    }

    public Set<Node> getNodes() {
        Set<Node> result = new HashSet<>();
        nodesMap.keySet().forEach((key)-> result.add(nodesMap.get(key)));
        return result;
    }

    public Node getNodeByUri(String uri) {
        return nodesMap.get(uri).clone();
    }

    public Node getTypeByUri(String uri) {
        return typesMap.get(uri).clone();
    }

    private void setTypes(Node types) { } //！！！不应使用 只提供给spring

    private void setNodes(Node nodes) { } //！！！不应使用 只提供给spring

    public Set<Triple> getProperties() {
        return new HashSet<>(properties);
    }

    public void addType(Node type) {
        Node theType = typesMap.get(type.getUri());
        if(theType!=null) return;
        //复制节点存入
        Node cloneNode = new Node();
        cloneNode.setId(typeId.getAndIncrement());
        cloneNode.setUri(type.getUri());
        cloneNode.setLabel_ZH(type.getLabel_ZH());
        cloneNode.setLabel_EN(type.getLabel_EN());
        typesMap.put(type.getUri(),cloneNode);
    }

    public void addNode(Node node) {
        Node theNode = nodesMap.get(node.getUri());
        if(theNode!=null) return;
        //获取类型节点
        Node typeNode = typesMap.get(node.getType().getUri());
        //复制节点存入
        Node cloneNode = new Node();
        cloneNode.setId(nodeId.getAndIncrement());
        cloneNode.setUri(node.getUri());
        cloneNode.setTypeId(typeNode.getId());
        cloneNode.setType(typeNode);
        cloneNode.setLabel_ZH(node.getLabel_ZH());
        cloneNode.setLabel_EN(node.getLabel_EN());
        nodesMap.put(node.getUri(),cloneNode);

    }

    public void addTriple(Triple property) {
        Node sourceNode = nodesMap.get(property.getSource().getUri());
        Node targetNode = nodesMap.get(property.getTarget().getUri());
        property.setSource(sourceNode);
        property.setTarget(targetNode);
        property.setSourceId(sourceNode.getId());
        property.setTargetId(targetNode.getId());
        properties.add(property);
        property.setId(propertyId.getAndIncrement());
    }

    /**
     * 根据uri获取基础类型
     * @param uri
     * @return
     */
    public static Node getBaseTypeByUri(String uri) {
        if(uri.equals(DefaultURI.baseElement)) return getBaseElementNode();
        else if(uri.equals(RDF.Property.getURI())) return getPropertyNode();
        else if(uri.equals(RDFS.Resource.getURI())) return getResourceNode();
        else if(uri.equals(RDFS.Class.getURI())) return getClassNode();
        else if(uri.equals(DefaultURI.xmlString)) return getXmlStringNode();
        return null;
    }
    private static Node getBaseElementNode(){
        return new Node(DefaultURI.baseElement,"基本元素","baseElement",null);
    }
    private static Node getClassNode(){
        return new Node(RDFS.Class.getURI(),"类型","class",getBaseElementNode());
    }
    private static Node getResourceNode(){
        return new Node(RDFS.Resource.getURI(),"资源","resource",getBaseElementNode());
    }
    private static Node getPropertyNode(){
        return new Node(RDF.Property.getURI(), "属性", "property",getBaseElementNode());
    }
    private static Node getXmlStringNode(){
        return new Node(DefaultURI.xmlString,"字符串","xmlString",getBaseElementNode());
    }

    /**
     * 在类型集合中添加基本类型Resource、Class、Property
     * 基类型的类型为null - 基类型不应被绘制(即不应被加入this.nodes)
     */
    public void buildBaseType(){
        addType(getBaseElementNode());
        addType(getPropertyNode());
        addType(getResourceNode());
        addType(getClassNode());
        addType(getXmlStringNode());
    }

    /**
     * 初始化图谱内部各节点id
     */
//    public void initContentId() {
//        {
//            AtomicInteger id = new AtomicInteger(1);
//            types.forEach((type)-> type.setId(id.getAndIncrement()));
//        }
//        {
//            AtomicInteger id = new AtomicInteger(1);
//            nodes.forEach((node)-> {
//                node.setId(id.getAndIncrement());
//
//            });
//        }
//        {
//            AtomicInteger id = new AtomicInteger(1);
//            properties.forEach((property)-> property.setId(id.getAndIncrement()));
//        }
//    }


}
